home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / ctask.zip / TSKASM.ASM < prev    next >
Assembly Source File  |  1988-07-01  |  7KB  |  414 lines

  1. ;
  2. ;    CTask - Scheduler and miscellaneous utilities
  3. ;
  4. ;    Public Domain Software written by
  5. ;        Thomas Wagner
  6. ;        Patschkauer Weg 31
  7. ;        D-1000 Berlin 33
  8. ;        West Germany
  9. ;
  10.  IFDEF at
  11. .186
  12.  ENDIF
  13.     name    tskasm
  14.     .model    large
  15. ;
  16.     public    scheduler
  17.     public    _schedule
  18.     public    _c_schedule
  19.     public    _sched_int
  20. ;
  21.     public    _tsk_dis_int
  22.     public    _tsk_ena_int
  23.     public    _tsk_cli
  24.     public    _tsk_sti
  25.     public    _tsk_dseg
  26.     public    _tsk_flags
  27.     public    _tsk_outp
  28.     public    _tsk_inp
  29.     public    _tsk_nop
  30. ;
  31. ;
  32.     include    tsk.mac
  33. ;
  34. INT_FLAG    =    2h    ; Int enable flag in upper byte of flag reg
  35. r_flags        =    24    ; Offset of flag register on task stack
  36. ;
  37.     .data?
  38. ;
  39.     extrn    _tsk_current: dword
  40.     extrn    _tsk_eligible: dword
  41.     extrn    _tsk_preempt: byte
  42.     extrn    _tsk_pretick: byte
  43.     extrn    _tsk_var_prior: byte
  44. ;
  45.     .data
  46. ;
  47. in_sched    db    0
  48. ;
  49.     .code
  50. ;                   
  51. _dgroup        dw    seg dgroup
  52. ;
  53. ;------------------------------------------------------------------------
  54. ;
  55. ;    enq    Enqueue tcb in queue. For local use only.
  56. ;        entry:    es:di = tcb to enqueue
  57. ;        exit:    -
  58. ;        uses:    ax, cx, dx, bp, di
  59. ;
  60. enq    macro
  61. ;
  62.     lds    bx,es:queue[di]        ; queue head pointer
  63.     mov    ax,ds
  64.     or    ax,bx    
  65.     jz    enq_end            ; nothing left to do if queue null
  66.     mov    dx,es:prior[di]        ; load priority of task
  67. enq_l:
  68.     mov    cx,bx            ; save last ptr
  69.     mov    bp,ds
  70.     lds    bx,next[bx]        ; load next
  71.     mov    ax,ds
  72.     or    ax,bx            ; end of chain?
  73.     jz    enq_found        ; then insert
  74.     cmp    dx,prior[bx]        ; compare priority
  75.     jbe    enq_l            ; loop if tasks prior less or equal
  76. ;
  77. enq_found:
  78.     mov    word ptr es:next[di],bx        ; set tasks next pointer
  79.     mov    word ptr es:next+2[di],ds
  80.     mov    bx,cx                ; last pointer
  81.     mov    ds,bp
  82.     mov    word ptr next[bx],di        ; last->next = task
  83.     mov    word ptr next+2[bx],es
  84. enq_end:
  85.     mov    ds,_dgroup
  86. ;
  87.     endm
  88. ;
  89. ;
  90. ;    upd_prior: Update priority of tasks in eligible queue.
  91. ;               Only activated if tsk_var_prior is nonzero.
  92. ;
  93. ;    NOTE:    This loop is not protected by interrupt disable.
  94. ;        Since it does not modify the queue itself, there
  95. ;        is no danger of race conditions.
  96. ;
  97. upd_prior    macro
  98. ;
  99.     les    di,_tsk_eligible
  100. pinc_loop:
  101.     mov    ax,es
  102.     or    ax,di            ; end of chain?
  103.     jz    updp_end
  104.     inc    es:prior[di]
  105.     jnz    pinc_nxt
  106.     dec    es:prior[di]
  107. pinc_nxt:
  108.     les    di,es:next[di]
  109.     jmp    pinc_loop
  110. ;
  111. updp_end:
  112. ;
  113.     endm
  114. ;
  115. ;
  116. ;    The scheduler. Note that this routine is entered with the stack
  117. ;    set up as for an interrupt handler.
  118. ;
  119. scheduler    proc    far
  120. ;
  121.     cli            ; better safe than sorry
  122.     push    ds
  123.     mov    ds,_dgroup
  124.     cmp    in_sched,0    ; already in the scheduler?
  125.     je    sched_ok    ; continue if not
  126.     pop    ds        ; else return immediately
  127.     iret
  128. ;
  129. sched_ok:
  130.     inc    in_sched
  131.     pop    ds
  132.     sti            ; we can now safely enable interrupts
  133.  IFNDEF at
  134.     push    ax
  135.     push    cx
  136.     push    dx
  137.     push    bx
  138.     push    sp
  139.     push    bp
  140.     push    si
  141.     push    di
  142.  ELSE
  143.     pusha
  144.  ENDIF
  145.     push    ds
  146.     push    es
  147. ;
  148.     mov    ds,_dgroup        ; establish addressing of our vars
  149. ;
  150.     cmp    _tsk_var_prior,0
  151.     je    no_var_pri
  152.     upd_prior            ; update priority
  153. ;
  154. no_var_pri:
  155.     cli                ; the following is critical
  156. ;
  157.     les    di,_tsk_current        ; get current tcb
  158.     mov    ax,es            ; check if NULL (current task killed)
  159.     or    ax,di
  160.     jz    no_current
  161. ;
  162.     mov    word ptr es:stack[di],sp ; store stack pointer & seg
  163.     mov    word ptr es:stack+2[di],ss
  164. ;
  165.     enq                ; Enqueue current task
  166. ;
  167. no_current:
  168.     mov    _tsk_pretick,0        ; No preemption tick
  169.     and    _tsk_preempt,1        ; Turn off temp preempt flag
  170. ;
  171. wait_elig:
  172.     cli
  173.     les    di,_tsk_eligible
  174. ;
  175. ;    If eligible queue empty, enter waiting loop
  176. ;
  177.     mov    ax,es
  178.     or    ax,di            ; is the eligible queue empty?
  179.     jnz    not_empty        ; jump if not
  180.     sti                       ; enable interrupts
  181.     nop
  182.     nop
  183.     jmp    wait_elig
  184. ;
  185. ;    Eligible queue not empty, activate first eligible task.
  186. ;
  187. not_empty:
  188.     mov    ax,word ptr es:next[di]        ; load next pointer
  189.     mov    word ptr _tsk_eligible,ax    ; remove from queue
  190.     mov    ax,word ptr es:next+2[di]
  191.     mov    word ptr _tsk_eligible+2,ax
  192. ;
  193.     mov    word ptr _tsk_current,di     ; set tcb into current
  194.     mov    word ptr _tsk_current+2,es
  195.     mov    ax,es:iniprior[di]        ; reset current tasks priority
  196.     mov    es:prior[di],ax
  197. ;
  198.     mov    in_sched,0            ; reset scheduler active flag
  199. ;
  200.     lds    si,es:stack[di]         ; load stack
  201.     or    byte ptr r_flags+1[si],INT_FLAG    ; enable interrupts
  202.     mov    es:state[di],ST_RUNNING        ; set task state
  203.     mov    cx,ds            ; switch stack
  204.     mov    ss,cx
  205.     mov    sp,si
  206.     pop    es            ; restore all registers
  207.     pop    ds
  208.  IFNDEF at
  209.     pop    di
  210.     pop    si
  211.     pop    bp
  212.     pop    bx            ; don't pop SP
  213.     pop    bx
  214.     pop    dx
  215.     pop    cx
  216.     pop    ax
  217.  ELSE
  218.     popa
  219.  ENDIF
  220.     iret
  221. ;
  222. scheduler    endp
  223. ;
  224. ;
  225. ;--------------------------------------------------------------------------
  226. ;
  227. ;
  228. ;    _sched_int  
  229. ;
  230. ;    Is the scheduler entry for interrupt handlers.
  231. ;    It checks if preemption is allowed, returning if not.
  232. ;    The stack is assumed to be set up as on interrupt entry.
  233. ;    
  234. _sched_int    proc    far
  235. ;
  236.     push    ds
  237.     push    bx
  238.     mov    ds,_dgroup
  239.     cmp    _tsk_preempt,0        ; preempt flags 0?
  240.     jne    no_sched        ; no scheduling if set
  241.     lds    bx,_tsk_current        ; current running task
  242.     test    flags[bx],F_CRIT    ; preemption allowed for this task?
  243.     jnz    no_sched        ; no scheduling if flag set
  244.     pop    bx            ; else go schedule
  245.     pop    ds
  246.     jmp    scheduler
  247. ;
  248. no_sched:
  249.     mov    ds,_dgroup
  250.     mov    _tsk_pretick,1        ; Mark preemption pending
  251.     pop    bx
  252.     pop    ds
  253.     iret
  254. ;
  255. _sched_int    endp
  256. ;
  257. ;
  258. ;    void far schedule (void)
  259. ;
  260. ;    Entry for calling the scheduler. Rearranges the stack to
  261. ;    contain flags.
  262. ;    NOTE: Uses ax,bx.
  263. ;
  264. _schedule    proc    far
  265. ;
  266.     pop    ax
  267.     pop    bx
  268.     pushf
  269.     push    bx
  270.     push    ax
  271.     cli
  272.     jmp    scheduler
  273. ;
  274. _schedule    endp
  275. ;
  276. ;
  277. ;    void far c_schedule (void)
  278. ;
  279. ;    Entry for conditionally calling the scheduler. Rearranges 
  280. ;    the stack to contain flags, then jumps to _sched_int.
  281. ;    NOTE: Uses ax,bx.
  282. ;
  283. _c_schedule    proc    far
  284. ;
  285.     pop    ax
  286.     pop    bx
  287.     pushf
  288.     push    bx
  289.     push    ax
  290.     cli
  291.     jmp    _sched_int
  292. ;
  293. _c_schedule    endp
  294. ;
  295. ;--------------------------------------------------------------------------
  296. ;
  297. ;    word tsk_dseg (void)
  298. ;
  299. ;    Returns current contents of DS register.
  300. ;
  301. _tsk_dseg    proc      far
  302.     mov    ax,ds
  303.     ret
  304. _tsk_dseg    endp
  305. ;
  306. ;
  307. ;    word tsk_flags (void)
  308. ;
  309. ;    Returns current contents of Flag register.
  310. ;
  311. _tsk_flags    proc    far
  312.     pushf
  313.     pop    ax
  314.     ret
  315. _tsk_flags    endp
  316. ;
  317. ;
  318. ;    int tsk_dis_int (void)
  319. ;
  320. ;    Returns current state of the interrupt flag (1 if ints were 
  321. ;    enabled), then disables interrupts.
  322. ;
  323. _tsk_dis_int    proc    far
  324. ;
  325.     pushf
  326.     pop    ax
  327.     mov    cl,9
  328.     shr    ax,cl
  329.     and    ax,1
  330.     cli
  331.     ret
  332. ;
  333. _tsk_dis_int    endp
  334. ;
  335. ;
  336. ;    void far tsk_ena_int (int state)
  337. ;
  338. ;    Enables interrupts if 'state' is nonzero.
  339. ;
  340. _tsk_ena_int    proc    far
  341. ;
  342.     push    bp
  343.     mov    bp,sp
  344.     mov    ax,6[bp]
  345.     pop    bp
  346.     or    ax,ax
  347.     jz    teiend
  348.     sti
  349. teiend:
  350.     ret
  351. ;
  352. _tsk_ena_int    endp
  353. ;
  354. ;
  355. ;    tsk_cli/tsk_sti: disable/enable int
  356. ;
  357. _tsk_cli    proc    far
  358.     cli
  359.     ret
  360. _tsk_cli    endp
  361. ;
  362. ;
  363. _tsk_sti    proc    far
  364.     sti
  365.     ret
  366. _tsk_sti    endp
  367. ;
  368. ;
  369. ;    tsk_inp/tsk_outp: input/output from/to port
  370. ;
  371. _tsk_inp    proc    far
  372. ;
  373.     push    bp
  374.     mov    bp,sp
  375.     mov    dx,6[bp]
  376.     in    al,dx
  377.     xor    ah,ah
  378.     pop    bp
  379.     ret
  380. ;
  381. _tsk_inp    endp
  382. ;
  383. ;
  384. _tsk_outp    proc    far
  385. ;
  386.     push    bp
  387.     mov    bp,sp
  388.     mov    dx,6[bp]
  389.     mov    al,8[bp]
  390.     out    dx,al
  391.     pop    bp
  392.     ret
  393. ;
  394. _tsk_outp    endp
  395. ;
  396. ;
  397. ;    void tsk_nop (void)
  398. ;
  399. ;    Do nothing. Used for very short delays.
  400. ;
  401. _tsk_nop    proc    far
  402. ;
  403.     jmp    short tnop1
  404. tnop1:
  405.     jmp    short tnop2
  406. tnop2:
  407.     ret
  408. ;
  409. _tsk_nop    endp
  410. ;
  411.     end
  412.  
  413.  
  414.